home *** CD-ROM | disk | FTP | other *** search
- /*
- * Title:
- * viewperstrans.c
- *
- * Authors:
- * Michael P. Schenck
- *
- * Purpose:
- * This module provides the view structure used to describe the
- * position of the viepoint and the structure of the view
- * volume. This view volume is used for clipping everything
- * outside of it out of the raster list. A view structure can
- * be allocated and then configured to be used as the current
- * view. After this, if displaygraphics() is called, it will
- * use this new view point. The view is controlled by specifying
- * a point you are looking at and then spherical coordinates to
- * the point you are looking from. D and f are the parameters
- * that control the far and near clipping plane.
- * The clipping implimented clips entire polygons if any of thier
- * verticies are outside the view volume. This can create some
- * bizzare visual artifacts if you have large polygons and are up
- * close to them. They could randomly appear and dissapear.
- * If a view structure could not be allocated, a NULL pointer is
- * returned.
- *
- * Copyright Info:
- * Copyright (C) 1993, 1994 -- by Michael P. Schenck,
- * (mps4466@ultb.isc.rit.edu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a copy of the GNU General Public License
- * write to the Free Software Foundation, 675 Mass Ave,
- * Cambridge, MA 02139, USA.
- *
- */
-
- #include <stdlib.h>
- #include <math.h>
- #include "/include/types.h"
- #include "/include/errors.h"
- #include "/include/matrix.h"
- #include "/include/database.h"
- #include "/include/viewperstrans.h"
-
- ULONG objectviewlist[MAXPOLYINVIEW],
- polyviewlist[MAXPOLYINVIEW],
- viewlistindex;
-
- extern struct Object *objects[MAXNUMOBJECTS];
- extern UWORD height,x_center,y_center;
-
- static FLOAT sintheta,costheta,sinphi,cosphi,scale,*v,*p,*rm;
-
- /* Open and allocate required matricies. */
-
- UBYTE openviewperstrans()
-
- {
- if((v = allocatematrix())==NULL)
- return(MEM_ALLOC_FAILURE);
- if((p = allocatematrix())==NULL) {
- freematrix(v);
- return(MEM_ALLOC_FAILURE);
- }
- if((rm = allocatematrix())==NULL) {
- freematrix(v);
- freematrix(p);
- return(MEM_ALLOC_FAILURE);
- }
- return(SUCCESS);
- }
-
- /* Get a raw view structure. */
-
- struct View *allocateview()
-
- {
- return((struct View *)malloc(sizeof(struct View)));
- }
-
- /* Configure the view by calculating new viewing and perspective
- transformation. */
-
- void configureview(struct View *view)
-
- {
- scale = (float)height; /* change to a constant smaller than the height and you will
- see the clipping occur for the entire view volume */
- sintheta = sin(view->theta);
- costheta = cos(view->theta);
- sinphi = sin(view->phi);
- cosphi = cos(view->phi);
-
- /* Construct viewing matrix. */
-
- *(v) = -sintheta;
- *(v+1) = -cosphi * costheta;
- *(v+2) = -sinphi * costheta;
- *(v+3) = 0.0;
- *(v+4) = costheta;
- *(v+5) = -cosphi * sintheta;
- *(v+6) = -sinphi * sintheta;
- *(v+7) = 0.0;
- *(v+8) = 0.0;
- *(v+9) = sinphi;
- *(v+10) = -cosphi;
- *(v+11) = 0.0;
- *(v+12) = view->x*sintheta-view->y*costheta;
- *(v+13) = view->x*cosphi*costheta+view->y*cosphi*sintheta-view->z*sinphi;
- *(v+14) = view->ro+view->x*sinphi*costheta+view->y*sinphi*sintheta+view->z*cosphi;
- *(v+15) = 1.0;
-
- /* Construct and concatenate perspective transformation matrix. */
-
- identitymatrix(p);
-
- *(p) = scale;
- *(p+5) = scale;
- *(p+10) = view->f/(view->f-view->d);
- *(p+11) = 1.0;
- *(p+14) = -(view->d*view->f/(view->f-view->d));
- *(p+15) = 0.0;
-
- multmatrix(v,p,rm);
- }
-
- /* Free up a view structure. */
-
- void releaseview(struct View *view)
-
- {
- free((void *)view);
- }
-
- /* Transform all the verticies in the view list, clip the polys,
- and build a raster list. */
-
- void transformvert()
- {
- register ULONG i,j,k,l;
- UBYTE *vertflag;
- ULONG *polygons,inside,curvert;
- FLOAT *verticies,*transvert,w,*rv;
-
- viewlistindex = 0;
- for(i=0;i<MAXNUMOBJECTS;i++) {
- if(objects[i] != NULL) {
-
- vertflag = objects[i]->vertflag;
- polygons = objects[i]->polygons;
- transvert = objects[i]->transvert;
- verticies = objects[i]->verticies;
-
- for(j=0;j<(objects[i]->numvert);j++)
- *(vertflag+j) = 0;
-
- for(j=0;j<objects[i]->numpoly*MAXPOLYVERT;j+=MAXPOLYVERT) {
- inside = TRUE;
- for(k=0;k<MAXPOLYVERT;k++) {
- if((curvert = *(polygons+j+k))==NOVERT)
- k=MAXPOLYVERT;
- else {
- if(!(*(vertflag+curvert))) {
- rv = transvert+curvert*4;
-
- /* Viewing transformation. */
-
- multvecandmat(verticies+curvert*4,rm,rv);
-
- /* Add clipping buffer to reduce visual artifacs inherent
- in this method of clipping (removing entire polygons!). */
-
- w = scale * (*(rv+3) + *(rv+3)*0.2);
-
- /* 3D clipping in homogeneous coords. */
-
- if((*rv>w)||(*rv<-w)||(*(rv+1)>w)||(*(rv+1)<-w)||(*(rv+2)<0.0)||(*(rv+2)>*(rv+3))) {
- *(vertflag+curvert) += 1;
- inside = FALSE;
- k = MAXPOLYVERT;
- }
- else {
- for(l=0;l<3;l++)
- *(rv+l) = (*(rv+l)) / (*(rv+3));
- *rv = *rv + x_center;
- *(rv+1) = *(rv+1) + y_center;
- }
- *(vertflag+curvert) += 1;
- }
- else {
- if(*(vertflag+curvert)==2){
- inside = FALSE;
- k = MAXPOLYVERT;
- }
- }
- }
- }
- if(inside) {
- objectviewlist[viewlistindex] = i;
- polyviewlist[viewlistindex] = j / MAXPOLYVERT;
- viewlistindex++;
- if(viewlistindex == MAXPOLYINVIEW)
- return;
- }
- }
- }
- }
- }
-
- /* Close module. */
-
- void closeviewperstrans()
-
- {
- freematrix(v);
- freematrix(p);
- freematrix(rm);
-
- }
-